package com.hk.core.authentication.api.reactive;

import com.hk.commons.util.Lazy;
import com.hk.commons.util.SpringContextHolder;
import com.hk.core.authentication.api.UserPrincipal;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import reactor.core.publisher.Mono;

/**
 * reactive  api 获取登录用户信息
 *
 * @author kevin
 * @date 2018-08-01 16:58
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public abstract class ReactiveSecurityContextUtils {

    private static final Lazy<ReactiveSecurityContext> SECURITY_CONTEXT = new Lazy<>(() ->
            SpringContextHolder.getBean(ReactiveSecurityContext.class), true);

    /**
     * 获取当前登陆用户信息
     *
     * @return {@link UserPrincipal}
     */
    public static Mono<UserPrincipal> getPrincipal() {
        return SECURITY_CONTEXT.get().getPrincipal();
    }

    /**
     * 获取当前登陆用户信息
     *
     * @return {@link UserPrincipal}
     */
    public static <T extends UserPrincipal> Mono<T> getPrincipalByType(Class<T> type) {
        return SECURITY_CONTEXT.get().getPrincipalByType(type);
    }

    /**
     * 判断当前用户是否有登陆
     *
     * @return 登陆返回 true,否则返回 false
     */
    public static Mono<Boolean> isAuthenticated() {
        return SECURITY_CONTEXT.getOptional()
                .map(ReactiveSecurityContext::isAuthenticated)
                .orElse(Mono.just(Boolean.FALSE));
    }

    /**
     * 判断当前登陆用户是否有任意指定权限
     */
    public static Mono<Boolean> hasAnyPermission(String... permissions) {
        return SECURITY_CONTEXT.getOptional()
                .map(securityContext -> securityContext.hasAnyPermission(permissions))
                .orElse(Mono.just(Boolean.FALSE));
    }

    /**
     * 判断当前登陆用户是否有指定权限
     */
    public static Mono<Boolean> hasPermission(String permission) {
        return SECURITY_CONTEXT.getOptional()
                .map(securityContext -> securityContext.hasPermission(permission))
                .orElse(Mono.just(Boolean.FALSE));
    }

    /**
     * 判断当前登陆用户是否有指定角色
     */
    public static Mono<Boolean> hasRole(String role) {
        return SECURITY_CONTEXT.getOptional()
                .map(securityContext -> securityContext.hasRole(role))
                .orElse(Mono.just(Boolean.FALSE));
    }

    /**
     * 判断当前登陆用户是否有任意指定角色
     */
    public static Mono<Boolean> hasAnyRole(String... roles) {
        return SECURITY_CONTEXT.getOptional()
                .map(securityContext -> securityContext.hasAnyRole(roles))
                .orElse(Mono.just(Boolean.FALSE));
    }
}
